import java.*;
import java.util.*;
import java.io.*;


class Transicion {
	public String lexema="";
	public Nodo nodoNexo;
	Transicion(Nodo _nodoNexo)
	{
		nodoNexo=_nodoNexo;
	}
	Transicion(String _lexema, Nodo _nodoNexo)
	{
		lexema=_lexema;
		nodoNexo=_nodoNexo;
	}
}

class Nodo {
	public static int Cuenta=0;
	public String nombre="q";
	public boolean esFinal=false;
	public boolean esInicial=false;
	public Nodo nodoFinal;
	public Vector<Transicion> transiciones=new Vector<Transicion>();
	Nodo () {
		this.nombre="q" + Nodo.Cuenta;
		Nodo.Cuenta++;
	}
	Nodo (Transicion[] _transiciones){
		for(int cursor=0; cursor<_transiciones.length; cursor++)
		{
			transiciones.add(_transiciones[cursor]);
		}
	}
	Nodo (boolean _esFinal)
	{
		this.esFinal = _esFinal;
	}
}

abstract class Reporte
{
	public static void GenerarArchivo(Nodo nodo, String path)
	{
		Vector<Nodo> porLeer = new Vector<Nodo>();
		Vector<Nodo> leidos = new Vector<Nodo>();
		int largo = 10;
		Vector<String> lexemas = new Vector<String>();
		
		porLeer.add(nodo);
		while(porLeer.size()>0)
		{
			Nodo nodoActual = porLeer.remove(0);
			if(Reporte.ExisteEnColeccion(leidos,nodoActual)==-1)
			{
				leidos.add(nodoActual);
				for(int cursor=0;cursor<nodoActual.transiciones.size();cursor++)
				{
					porLeer.add(nodoActual.transiciones.get(cursor).nodoNexo);
					if(Reporte.ExisteEnColeccion(lexemas,nodoActual.transiciones.get(cursor).lexema)==-1)
					{
						lexemas.add(nodoActual.transiciones.get(cursor).lexema);
					}
				}
			}
		}
		
		String mensaje = Reporte.StringLargo("Estados",largo)+ "|";
		for(int cursor=0;cursor<lexemas.size();cursor++)
		{
			mensaje = mensaje  + Reporte.StringLargo(lexemas.get(cursor),largo) + "|";
		}
		mensaje = mensaje + "\n";
		
		for(int cursor=0;cursor<leidos.size();cursor++)
		{
			Nodo nodoActual = leidos.get(cursor);
			String esTermino = "";
			if(nodoActual.esFinal) esTermino="*";
			mensaje=mensaje+Reporte.StringLargo(nodoActual.nombre + esTermino,largo) + "|";
			for(int cursorLexema=0;cursorLexema<lexemas.size();cursorLexema++)
			{
				String lexema = lexemas.get(cursorLexema);
				String subMensaje = "";
				for(int cursorTransicion =0; cursorTransicion<nodoActual.transiciones.size();cursorTransicion++)
				{
				//Reporte.StringLargo("",largo);
					if(nodoActual.transiciones.get(cursorTransicion).lexema.equals(lexema))
					{
						if(!subMensaje.equals("")) subMensaje=subMensaje+",";
						subMensaje=subMensaje+nodoActual.transiciones.get(cursorTransicion).nodoNexo.nombre;
						
					}
				}
				mensaje=mensaje+Reporte.StringLargo(subMensaje,largo) + "|";
			}
			mensaje=mensaje+"\n";
		}
		
		
		try{          
			FileWriter file1 = new FileWriter(path+".txt");
			BufferedWriter buff = new BufferedWriter(file1);

			buff.write(mensaje);

			buff.close();
			file1.close();
			System.out.println("Se genero el AFDN con movimientos espontaneos en: "+path+".txt");
            }
            catch(IOException e){
               System.out.println("Error: no se puede escribir la AFDN con movimientos espontaneos.");
            }
	}
	public static String StringLargo(String mensaje, int largo)
	{
		String _mensaje = mensaje;
		while(_mensaje.length()<largo) _mensaje = _mensaje + " ";
		return _mensaje;
	}
	public static int ExisteEnColeccion(Vector<Nodo> coleccion, Nodo nodo)
	{
		for(int cursor=0;cursor<coleccion.size();cursor++)
		{
			if(coleccion.get(cursor)==nodo) return cursor;
		}
		return -1;
	}
	public static int ExisteEnColeccion(Vector<String> coleccion, String nodo)
	{
		for(int cursor=0;cursor<coleccion.size();cursor++)
		{
			if(coleccion.get(cursor).equals(nodo)) return cursor;
		}
		return -1;
	}
}